package com.bwie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bwie.mapper.BrandMapper;
import com.bwie.mapper.DictMapper;
import com.bwie.mapper.ProdFileMapper;
import com.bwie.poi.StringUtils;
import com.bwie.pojo.*;
import com.bwie.service.UserFeign;
import com.bwie.utils.JwtsUtils;
import com.bwie.utils.R;
import com.bwie.vo.EsProdVo;
import org.bouncycastle.est.ESTService;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.mapper.ProdsMapper;
import com.bwie.service.ProdsService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
* @author :Beyond🎸🎸
* @date : 2025-10-20 20:01:32
* @description
* ${description}
**/
@Service
public class ProdsServiceImpl extends ServiceImpl<ProdsMapper, Prods> implements ProdsService{

    @Autowired
    private ProdsMapper prodsMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DictMapper dictMapper;


    @Autowired
    private BrandMapper brandMapper;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ProdFileMapper prodFileMapper;

    @Autowired
    private ElasticsearchRestTemplate elasticsearchRestTemplate;


    @Override
    public R createDictToRedis() {
        System.out.println("开始存入字典表到缓存");
        List<Dict> dicts = dictMapper.selectList(null);

        for (Dict dict : dicts) {
            redisTemplate.opsForHash().put("key"+dict.getDictPid(),dict.getDictValue().toString(), JSON.toJSONString(dict));
        }

        return R.OK();
    }

    @Override
    public R getDictValueByRedis(Integer dictPid) {
        ArrayList<Dict> dicts = new ArrayList<>();

        Boolean yes = redisTemplate.hasKey("key" + dictPid);

        if(yes != null && yes){
            List<Object> values = redisTemplate.opsForHash().values("key" + dictPid);
            for (Object value : values) {
                dicts.add(JSON.parseObject(value.toString(), Dict.class));
            }
            return R.OK(dicts);
        }
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Dict::getDictPid,dictPid);
        List<Dict> dictList = dictMapper.selectList(wrapper);

        if(StringUtils.isNotEmpty(dictList)){
            for (Dict dict : dictList) {
                redisTemplate.opsForHash().put("key"+dict.getDictPid(),dict.getDictValue().toString(),JSON.toJSONString(dict));
            }
        }
        return R.OK(dictList);
    }

    @Override
    public R getSelectBrand() {

        LambdaQueryWrapper<Brand> wrapper = new QueryWrapper<Brand>().lambda();
        wrapper.eq(Brand::getDeleteFlag,0);

        List<Brand> brands = brandMapper.selectList(wrapper);

        return R.OK(brands);
    }

    @Override
    public R checkIfRepeat(Prods prods) {

        LambdaQueryWrapper<Prods> queryWrapper = new QueryWrapper<Prods>().lambda();
        queryWrapper.eq(Prods::getDeleteFlag,0);
        queryWrapper.eq(Prods::getProdSpu,prods.getProdSpu());

        Prods one = prodsMapper.selectOne(queryWrapper);
        if(one!=null){
            return R.ERROR(500,"该条信息已经存在");
        }else{
           return R.OK();
        }
    }

    @Override
    public R saveProduct(Prods prods) {

        String token = request.getHeader("token");

        Integer userIdByToken = JwtsUtils.getUserIdByToken(token);

        prods.setCreateBy(userIdByToken);
        prods.setCreateTime(new Date());
        prods.setUpdateBy(userIdByToken);
        prods.setUpdateTime(new Date());
        prods.setDeleteFlag(0);
        prods.setProdStatus(0);

        User feigenUser = userFeign.getUserNameToSave(userIdByToken);
        System.out.println("调用用户结果："+ feigenUser);
        prodsMapper.insert(prods);
        return R.OK();
    }


    @Override
    public R joinSelectProdList(Prods prods) {

        Page<Prods> page = new Page<>(prods.getPageNum(), prods.getPageSize());

        Page<Prods> prodList = prodsMapper.joinSelectProdList(page,prods.getKeyWord(),null);

        return R.OK(prodList);
    }

    @Override
    public R saveProFileOk(ProdFile prodFile) {

        String token = request.getHeader("token");

        Integer userIdByToken = JwtsUtils.getUserIdByToken(token);

        prodFile.setCreateBy(userIdByToken);
        prodFile.setCreateTime(new Date());
        prodFile.setUpdateBy(userIdByToken);
        prodFile.setUpdateTime(new Date());

        prodFileMapper.insert(prodFile);

        return R.OK();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R deleteGoodsBatch(List<Integer> ids) {

        for (Integer id : ids) {
            Prods prods = prodsMapper.selectById(id);
            prods.setDeleteFlag(1);
            prodsMapper.updateById(prods);

            LambdaUpdateWrapper<ProdFile> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(ProdFile::getProdId,id);
            prodFileMapper.delete(wrapper);
        }

        return R.OK();
    }
/**
* @Author: Hui Shao
* @Description: 查询Es商品
* @Param: [prods]
* @return: com.bwie.utils.R
* @Date: 2025/10/31 11:45
*/
    @Override
    public R joinSelectProdListByEs(Prods prods) {
//        1、定义分页组件
//        es分页查询，页数索引是从0开始的
        Integer num = 0;
        if(prods.getPageNum()!=null){
        num=prods.getPageNum()-1;
        }
       PageRequest pageRequest = PageRequest.of(num,prods.getPageSize()==null?2:prods.getPageSize());
//        2、构建查询条件
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
//        根据商品状态进行精确查找
        if(prods.getProdStatus()!=null){
            boolQueryBuilder.must(QueryBuilders.termQuery("prodStatus",prods.getProdStatus()));
        }
//        根据商品名称进行分词模糊匹配
        if(StringUtils.isNotEmpty(prods.getProdName())){
            boolQueryBuilder.must(QueryBuilders.matchQuery("prodName",prods.getProdName()));
        }
//        根据创建时间进行范围匹配
        if(StringUtils.isNotEmpty(prods.getBeginTime())&&StringUtils.isNotEmpty(prods.getEndTime())){
            boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").timeZone("GMT+8").from(prods.getBeginTime()).to(prods.getEndTime()));

        }
//        3、构建排序
        FieldSortBuilder fieldSortBuilder = SortBuilders.fieldSort("prodId").order(SortOrder.DESC);
//        高亮显示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
////        分组
//        TermsAggregationBuilder termsAggregationBuilder = AggregationBuilders.terms("group_status")
//                .field("prodStatus");
        highlightBuilder.field("prodName").preTags("<font color='red'>").postTags("</fontu>");
//        4、构建查询器
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        NativeSearchQueryBuilder nativeSearchQueryBuilder = builder.
//                分页插件
        withPageable(pageRequest)
//                查询条件
                .withQuery(boolQueryBuilder)
//               排序
                .withSort(fieldSortBuilder)
//        高亮显示
                .withHighlightBuilder(highlightBuilder);
//        分组
//                .addAggregation(termsAggregationBuilder);
//        5、从es查询数据
        SearchHits<EsProdVo> search = elasticsearchRestTemplate.search(builder.build(), EsProdVo.class);
        ArrayList<EsProdVo> esProdVoList = new ArrayList<>();
        System.out.println("查询出来的数据为："+JSONObject.toJSONString(search));
        List<SearchHit<EsProdVo>> searchHits = search.getSearchHits();
        for (SearchHit<EsProdVo> searchHit : searchHits) {
            EsProdVo content = searchHit.getContent();
            List<String> prodName = searchHit.getHighlightField("prodName");
            if(prodName!=null&&prodName.size()>0){
                content.setProdName(prodName.get(0));

            }
            esProdVoList.add(content);
        }
        Page<EsProdVo> esProdVoPage = new Page<>(prods.getPageNum(), prods.getPageSize());
        esProdVoPage.setRecords(esProdVoList);
        esProdVoPage.setTotal(search.getTotalHits());
        //        6、组装数据返回给前端
        return R.OK(esProdVoPage);
    }

    @Override
    public R batchUpProd(List<Integer> ids) {
//        把需要上架的商品信息同步到es当中
        for (Integer id : ids) {
//            先将商品信息改成已上架的状态
            Prods byId = this.getById(id);
            byId.setProdStatus(2);
            byId.setUpdateTime(new Date());
            this.updateById(byId);
//            从数据库当中查询需要同步的数据
            Prods prods = prodsMapper.selectProdInfoToEs(id);
            EsProdVo esProdVo = new EsProdVo();
            BeanUtil.copyProperties(prods,esProdVo);
            elasticsearchRestTemplate.save(esProdVo);
        }

        return R.OK();
    }
}
